package com.ice.work.moment.ticket.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.honeybee.cloud.framework.base.exception.business.BaseBizException;
import com.honeybee.cloud.framework.common.enums.DataStatusEnum;
import com.honeybee.cloud.framework.common.http.HttpClient;
import com.honeybee.cloud.framework.common.http.HttpHeaderEnum;
import com.honeybee.cloud.framework.common.idwork.IdWorker;
import com.ice.work.moment.facade.ticket.constant.SystemConstant;
import com.ice.work.moment.facade.ticket.constant.TicketUrl;
import com.ice.work.moment.facade.ticket.dto.CookieDTO;
import com.ice.work.moment.facade.ticket.mapper.CookieConvertMapper;
import com.ice.work.moment.facade.ticket.mapper.ParamConvertMapper;
import com.ice.work.moment.facade.ticket.model.Cookie;
import com.ice.work.moment.facade.ticket.param.CookieParam;
import com.ice.work.moment.ticket.dao.cookie.CookieRepository;
import com.ice.work.moment.ticket.service.ICookieService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.ice.work.moment.facade.ticket.enums.TicketBizExceptionEnum.COOKIE_NOT_FOUND;

/**
 * @Description
 * @Author DELL
 * @Create 2019-05-16
 * @Since 1.0.0
 */
@Service
@Slf4j
public class CookieServiceImpl implements ICookieService {


    @Autowired
    private HttpClient httpClient;
    @Autowired
    private CookieRepository cookieRepository;

    @Autowired
    private IdWorker idWorker;

    @Override
    public CookieDTO findByLoginName(String loginName) throws BaseBizException {
        Cookie cookie = cookieRepository.findByLoginNameAndDataStatus(loginName, DataStatusEnum.VALID.key);
        CookieDTO cookieDTO;
        if (Objects.nonNull(cookie)) {
            if (!DateUtil.isExpired(cookie.getExpireAt(), DateField.HOUR, SystemConstant.COOKIE_EXPIRE_TIME, new Date())) {
                cookieDTO = getCookieFromService(loginName, cookie);
            } else {
                cookieDTO = CookieConvertMapper.INSTANCE.toDTO(cookie);
            }
            return getCookieStore(cookieDTO);
        }

        cookieDTO = getCookieFromService(loginName, null);
        return getCookieStore(cookieDTO);
    }

    /**
     * 获取最终的cookiestore
     *
     * @param cookieDTO
     * @return
     */
    private CookieDTO getCookieStore(CookieDTO cookieDTO) {
        if (Objects.isNull(cookieDTO)) {
            cookieDTO = getCookieFromService(SystemConstant.DEFAULT_LOGIN_NAME, null);
        }
        if (Objects.isNull(cookieDTO.getCookieStore())) {
            cookieDTO.setCookieStore(new BasicCookieStore());
        }
        if (CollectionUtils.isEmpty(cookieDTO.getCookieStore().getCookies())) {
            BasicCookieStore cookieStore = cookieDTO.getCookieStore();
            BasicClientCookie expCookie = new BasicClientCookie(SystemConstant.RAIL_EXPIRATION, String.valueOf(cookieDTO.getExpireAt().getTime()));
            expCookie.setDomain(TicketUrl.HOST_12306_URL);
            expCookie.setPath("/");
            cookieStore.addCookie(expCookie);

            BasicClientCookie deviceCookie = new BasicClientCookie(SystemConstant.RAIL_DEVICE_ID, cookieDTO.getCode());
            deviceCookie.setDomain(TicketUrl.HOST_12306_URL);
            deviceCookie.setPath("/");
            cookieStore.addCookie(deviceCookie);
            cookieDTO.setCookieStore(cookieStore);
        }
        return cookieDTO;
    }

    @Override
    public CookieDTO findByAppKey(String appKey) throws BaseBizException {
        Cookie cookie = cookieRepository.findByAppKeyAndDataStatus(appKey, DataStatusEnum.VALID.key);
        CookieDTO cookieDTO = CookieConvertMapper.INSTANCE.toDTO(cookie);
        return getCookieStore(cookieDTO);
    }

    @Override
    public boolean add(Cookie cookie) throws BaseBizException {
        Assert.notNull(cookie, "cookie not null");
        return cookieRepository.saveOrUpdate(cookie);
    }

    @Override
    public void deleteByAppKey(String appKey) throws BaseBizException {
        Assert.notNull(appKey, "appKey not null");
        cookieRepository.deleteByAppKey(appKey);
    }

    private CookieDTO getCookieFromService(String loginName, Cookie exists) throws BaseBizException {
        log.info("开始获取设备码");
        try {
            String url = TicketUrl.DEVICE_ID_URL.replace("{time}", String.valueOf(System.currentTimeMillis()));
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.INDEX_HTML);
            String result = httpClient.sendForm(url, header);

            if (Objects.isNull(result)) {
                throw new BaseBizException(COOKIE_NOT_FOUND.getParentCode(), COOKIE_NOT_FOUND.getSubCode(), COOKIE_NOT_FOUND.getMessage());
            }
            result = result.replaceAll("callbackFunction\\('", "").replaceAll("'\\)", "");
            CookieParam cookieParam = JSONObject.parseObject(result, CookieParam.class);
            if (Objects.isNull(cookieParam)) {
                throw new BaseBizException(COOKIE_NOT_FOUND.getParentCode(), COOKIE_NOT_FOUND.getSubCode(), COOKIE_NOT_FOUND.getMessage());
            }
            Cookie cookie = ParamConvertMapper.INSTANCE.toModel(cookieParam);
            cookie.setLoginName(loginName);
            cookie.setCreateAt(new Date());
            cookie.setDataStatus(DataStatusEnum.VALID.key);
            if (Objects.isNull(exists)) {
                cookie.setId(idWorker.nextId());
            } else {
                cookie.setId(exists.getId());
            }
            add(cookie);
            return CookieConvertMapper.INSTANCE.toDTO(cookie);
        } catch (Exception e) {
            log.error("获取设备码异常", e);
            throw new BaseBizException(COOKIE_NOT_FOUND.getParentCode(), COOKIE_NOT_FOUND.getSubCode(), COOKIE_NOT_FOUND.getMessage());
        }
    }


    /**
     * 用不上了
     *
     * @return
     */
    @Deprecated
    private String getAlgId() {
        try {
            Map<String, String> header = Maps.newHashMap();
            header.put(HttpHeaderEnum.REFERER.value, TicketUrl.INDEX_HTML);
            String result = httpClient.sendForm(TicketUrl.ALG_URL, header);
            log.info("请求内容:{}", result);
            if (Objects.isNull(result)) {
                return SystemConstant.DEFAULT_ALG_ID;
            }
            //截取
            String regex = "algID\\\\x3d(.*?)\\\\x26";
            Pattern pattern = Pattern.compile(regex);
            Matcher m = pattern.matcher(result);
            while (m.find()) {
                return m.group(1);
            }
        } catch (Exception e) {
            log.error("获取algId异常", e);
        }
        return SystemConstant.DEFAULT_ALG_ID;
    }
}
